From c7e49fb3e445ebf9bb1418cddcbd0cf2ac5d8400 Mon Sep 17 00:00:00 2001 From: oliskoli Date: Fri, 25 May 2007 10:13:21 +0000 Subject: [PATCH] Remove proximity and temperature from garmin special data. Extend wpt_flags with members for proximity and temperature. Define macros for easy access to 'flagged' waypoint fields (as GMSD). --- compegps.c | 7 +- defs.h | 5 + g7towin.c | 4 +- garmin_fs.c | 37 ++-- garmin_fs.h | 4 - garmin_txt.c | 8 +- gdb.c | 10 +- gpilots.c | 2 +- kml.c | 2 +- mapsource.c | 4 +- ozi.c | 4 +- stmsdf.c | 2 +- unicsv.c | 479 +++++++++++++++++++++++++++++++++++++++++---------- 13 files changed, 433 insertions(+), 135 deletions(-) diff --git a/compegps.c b/compegps.c index b65b6912b..0aa41ef40 100644 --- a/compegps.c +++ b/compegps.c @@ -205,8 +205,7 @@ parse_wpt_info(const char *buff, waypoint *wpt) /* "w" */ case 7: break; /* ??? */ case 8: /* radius */ fx = atof(c); - if (fx > 0) - wpt->proximity = fx; + if (fx > 0) WAYPT_SET(wpt, proximity, fx); break; } } @@ -450,7 +449,7 @@ write_waypt_cb(const waypoint *wpt) gbfprintf(fout, " %s", wpt->description); gbfprintf(fout, "\n"); - if ((wpt->icon_descr != NULL) || (wpt->proximity > 0.0) || \ + if ((wpt->icon_descr != NULL) || (wpt->wpt_flags.proximity) || \ (option_icon != NULL)) { char *icon = option_icon; @@ -459,7 +458,7 @@ write_waypt_cb(const waypoint *wpt) gbfprintf(fout, "w %s,0,0.0,16777215,255,1,7,,%.1f\n", (icon != NULL) ? icon : "Waypoint", - (wpt->proximity > 0.0f) ? wpt->proximity : 0.0); + WAYPT_GET(wpt, proximity, 0)); } xfree(name); } diff --git a/defs.h b/defs.h index c0c68e56d..7c19a356d 100644 --- a/defs.h +++ b/defs.h @@ -283,8 +283,13 @@ typedef struct { unsigned int icon_descr_is_dynamic:1; unsigned int shortname_is_synthetic:1; unsigned int cet_converted:1; /* strings are converted to UTF8; interesting only for input */ + unsigned int temperature:1; /* temperature field set */ + unsigned int proximity:1; /* proximity field set */ } wp_flags; +#define WAYPT_SET(wpt,member,val) { wpt->member = (val); wpt->wpt_flags.member = 1; } +#define WAYPT_GET(wpt,member,def) (wpt->wpt_flags.member) ? (wpt->member) : (def) + /* * This is a waypoint, as stored in the GPSR. It tries to not * cater to any specific model or protocol. Anything that needs to diff --git a/g7towin.c b/g7towin.c index 5c52a7751..a3e2517b1 100644 --- a/g7towin.c +++ b/g7towin.c @@ -183,12 +183,12 @@ parse_line(char *buff, int index, const char *delimiter, waypoint *wpt) /* !!! NO BREAK !!! */ case WPT_cD_OFS + 1: case WPT_cB_OFS + 6: - GMSD_SET(temperature, atof(cin)); + WAYPT_SET(wpt, temperature, atof(cin)); break; case WAYPT__OFS + 6: /* proximity */ case WPT_cD_OFS + 2: - GMSD_SET(proximity, atof(cin)); + WAYPT_SET(wpt, proximity, atof(cin)); break; case WPT_cB_OFS + 5: diff --git a/garmin_fs.c b/garmin_fs.c index 47afd54c8..d9c9a5ece 100644 --- a/garmin_fs.c +++ b/garmin_fs.c @@ -103,8 +103,8 @@ garmin_fs_xml_fprint(gbfile *ofd, const waypoint *waypt) if ((gmsd->flags.category && gmsd->category) || gmsd->flags.depth || - gmsd->flags.proximity || - gmsd->flags.temperature || + waypt->wpt_flags.proximity || + waypt->wpt_flags.temperature || gmsd->flags.display) { int space = 1; @@ -115,10 +115,10 @@ garmin_fs_xml_fprint(gbfile *ofd, const waypoint *waypt) "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " \ "xsi:schemaLocation=\"http://www.garmin.com/xmlschemas/GpxExtensions/v2 " \ "http://www.garmin.com/xmlschemas/GpxExtensions/v2/GpxExtensionsv2.xsd\">\n", space++ * 2, ""); - if (gmsd->flags.proximity) - gbfprintf(ofd, "%*s%.6f\n", space * 2, "", gmsd->proximity); - if (gmsd->flags.temperature) - gbfprintf(ofd, "%*s%.6f\n", space * 2, "", gmsd->temperature); + if (waypt->wpt_flags.proximity) + gbfprintf(ofd, "%*s%.6f\n", space * 2, "", waypt->proximity); + if (waypt->wpt_flags.temperature) + gbfprintf(ofd, "%*s%.6f\n", space * 2, "", waypt->temperature); if (gmsd->flags.depth) gbfprintf(ofd, "%*s%.6f\n", space * 2, "", gmsd->depth); if (gmsd->flags.display) @@ -180,10 +180,19 @@ garmin_fs_xml_convert(const int base_tag, int tag, const char *cdatastr, waypoin tt_garmin_category, -> 7 */ switch(tag) { - case 2: GMSD_SET(proximity, atof(cdatastr)); break; - case 3: GMSD_SET(temperature, atof(cdatastr)); break; - case 4: GMSD_SET(depth, atof(cdatastr)); break; - case 5: if (case_ignore_strcmp(cdatastr, "SymbolOnly") == 0) { + case 2: + waypt->proximity = atof(cdatastr); + waypt->wpt_flags.proximity = (*cdatastr); + break; + case 3: + waypt->temperature = atof(cdatastr); + waypt->wpt_flags.temperature = (*cdatastr); + break; + case 4: + GMSD_SET(depth, atof(cdatastr)); + break; + case 5: + if (case_ignore_strcmp(cdatastr, "SymbolOnly") == 0) { GMSD_SET(display, gt_display_mode_symbol); } else if (case_ignore_strcmp(cdatastr, "SymbolAndDescription") == 0) { @@ -270,8 +279,8 @@ garmin_fs_garmin_after_read(const GPS_PWay way, waypoint *wpt, const int protoid /* flagged data fields */ GMSD_SET(display, gt_switch_display_mode_value(way->dspl, gps_waypt_type, 1)); if (way->category != 0) GMSD_SET(category, way->category); - if (way->dst < 1.0e25f) GMSD_SET(proximity, way->dst); - if (way->temperature_populated) GMSD_SET(temperature, way->temperature); + if (way->dst < 1.0e25f) WAYPT_SET(wpt, proximity, way->dst); + if (way->temperature_populated) WAYPT_SET(wpt, temperature, way->temperature); if (way->dpth < 1.0e25f) GMSD_SET(depth, way->dpth); GMSD_SETNSTR(cc, way->cc, sizeof(way->cc)); GMSD_SETNSTR(state, way->state, sizeof(way->state)); @@ -295,8 +304,8 @@ garmin_fs_garmin_before_write(const waypoint *wpt, GPS_PWay way, const int proto GMSD_GET(display, way->dspl), gps_waypt_type, 0); way->category = GMSD_GET(category, way->category); way->dpth = GMSD_GET(depth, way->dpth); - way->dst = GMSD_GET(proximity, way->dpth); - way->temperature = GMSD_GET(temperature, way->temperature); + way->dst = WAYPT_GET(wpt, proximity, way->dpth); + way->temperature = WAYPT_GET(wpt, temperature, way->temperature); GMSD_GETNSTR(cc, way->cc, sizeof(way->cc)); GMSD_GETNSTR(city, way->city, sizeof(way->city)); diff --git a/garmin_fs.h b/garmin_fs.h index 7fb36f476..eda53d320 100644 --- a/garmin_fs.h +++ b/garmin_fs.h @@ -69,8 +69,6 @@ typedef struct { unsigned int display:1; unsigned int category:1; unsigned int depth:1; - unsigned int proximity:1; - unsigned int temperature:1; unsigned int city:1; unsigned int state:1; unsigned int facility:1; @@ -94,8 +92,6 @@ typedef struct garmin_fs_s gbint32 display; gbint16 category; double depth; /* depth in meters */ - double proximity; /* proximity distance in meters */ - double temperature; char *city; /* city name */ char *facility; /* facility name */ char *state; /* state */ diff --git a/garmin_txt.c b/garmin_txt.c index 3638510d3..7f17f0b19 100644 --- a/garmin_txt.c +++ b/garmin_txt.c @@ -581,12 +581,12 @@ write_waypt(const waypoint *wpt) print_distance(x, 1, 0); gbfprintf(fout, "\t"); - x = GMSD_GET(proximity, unknown_alt); + x = WAYPT_GET(wpt, proximity, unknown_alt); if (x != unknown_alt) print_distance(x, 0, 0); gbfprintf(fout, "\t"); - x = GMSD_GET(temperature, unknown_alt); + x = WAYPT_GET(wpt, temperature, unknown_alt); if (x != unknown_alt) { if (gtxt_flags.celsius) gbfprintf(fout, "%.f C", x); @@ -1130,8 +1130,8 @@ parse_waypoint(void) break; case 5: if (parse_distance(str, &d)) wpt->altitude = d; break; case 6: if (parse_distance(str, &d)) GMSD_SET(depth, d); break; - case 7: if (parse_distance(str, &d)) GMSD_SET(proximity, d); break; - case 8: if (parse_temperature(str, &d)) GMSD_SET(temperature, d); break; + case 7: if (parse_distance(str, &d)) WAYPT_SET(wpt, proximity, d); break; + case 8: if (parse_temperature(str, &d)) WAYPT_SET(wpt, temperature, d); break; case 9: if (parse_display(str, &i)) GMSD_SET(display, i); break; case 10: break; /* skip color */ case 11: diff --git a/gdb.c b/gdb.c index 464899f37..96fe4bd49 100644 --- a/gdb.c +++ b/gdb.c @@ -103,8 +103,8 @@ /*******************************************************************************/ -/* static char gdb_release[] = "$Revision: 1.51 $"; */ -static char gdb_release_date[] = "$Date: 2007/05/04 08:41:41 $"; +/* static char gdb_release[] = "$Revision: 1.52 $"; */ +static char gdb_release_date[] = "$Date: 2007/05/25 10:13:21 $"; static gbfile *fin, *fout; static int gdb_ver, gdb_category, gdb_via, gdb_roadbook; @@ -499,7 +499,7 @@ read_waypoint(gt_waypt_classes_e *waypt_class_out) #endif if (FREAD_C == 1) { double proximity = gbfgetdbl(fin); - GMSD_SET(proximity, proximity); + WAYPT_SET(res, proximity, proximity); #if GDB_DEBUG DBG(GDB_DBG_WPTe, 1) printf(MYNAME "-wpt \"%s\" (%d): Proximity = %.1f\n", @@ -1154,7 +1154,7 @@ write_waypoint( FWRITE_LATLON(wpt->longitude); /* longitude */ FWRITE_DBL(wpt->altitude, unknown_alt); /* altitude */ FWRITE_CSTR(wpt->notes); - FWRITE_DBL(GMSD_GET(proximity, 0), 0); /* proximity */ + FWRITE_DBL(WAYPT_GET(wpt, proximity, 0), 0); /* proximity */ FWRITE_i32(display); /* display */ FWRITE_i32(0); /* color (colour) */ FWRITE_i32(icon); /* icon */ @@ -1195,7 +1195,7 @@ write_waypoint( } FWRITE_i16(GMSD_GET(category, gdb_category)); - FWRITE_DBL(GMSD_GET(temperature, 0), 0); + FWRITE_DBL(WAYPT_GET(wpt, temperature, 0), 0); FWRITE_TIME(wpt->creation_time); /* VERSION DEPENDENT CODE */ diff --git a/gpilots.c b/gpilots.c index b59e2a409..8fb1cbcc3 100644 --- a/gpilots.c +++ b/gpilots.c @@ -277,7 +277,7 @@ data_read(void) fi.i = le_read32(&rec->wpt.d108.dpth); wpt_tmp->depth = fi.f; fi.i = le_read32(&rec->wpt.d108.dist); - wpt_tmp->proximity = fi.f; + WAYPT_SET(wpt_tmp, proximity, fi.f); wpt_tmp->wpt_flags.icon_descr_is_dynamic = 0; wpt_tmp->icon_descr = gt_find_desc_from_icon_number((rec->wpt.d108.smbl[1] << 8) + rec->wpt.d108.smbl[0], PCX, NULL); waypt_add(wpt_tmp); diff --git a/kml.c b/kml.c index 38564903b..47ad9937e 100644 --- a/kml.c +++ b/kml.c @@ -537,7 +537,7 @@ static void kml_output_description(const waypoint *pt) if (pt->altitude != unknown_alt) TD2("Altitude: %.1f %s", alt, alt_units); if (pt->heartrate) TD("Heart rate: %d", pt->heartrate); if (pt->cadence) TD("Cadence: %d", pt->cadence); - if (pt->temperature) TD("Temperature: %.1f", pt->temperature); + if (pt->wpt_flags.temperature) TD("Temperature: %.1f", pt->temperature); if (pt->speed > 0) { char *spd_units; double spd = fmt_speed(pt->speed, &spd_units); diff --git a/mapsource.c b/mapsource.c index edc5afd69..3825e7ab4 100644 --- a/mapsource.c +++ b/mapsource.c @@ -582,7 +582,7 @@ mps_waypoint_r(FILE *mps_file, int mps_ver, waypoint **wpt, unsigned int *mpscla thisWaypoint->latitude = GPS_Math_Semi_To_Deg(lat); thisWaypoint->longitude = GPS_Math_Semi_To_Deg(lon); thisWaypoint->altitude = mps_altitude; - thisWaypoint->proximity = mps_proximity; + if (mps_proximity != unknown_alt) WAYPT_SET(thisWaypoint, proximity, mps_proximity); thisWaypoint->depth = mps_depth; /* might need to change this to handle version dependent icon handling */ @@ -616,7 +616,7 @@ mps_waypoint_w(FILE *mps_file, int mps_ver, const waypoint *wpt, const int isRou int colour = 0; /* (unknown colour) black is 1, white is 16 */ double mps_altitude = wpt->altitude; - double mps_proximity = (mpsuseprox ? wpt->proximity : unknown_alt); + double mps_proximity = (mpsuseprox ? WAYPT_GET(wpt, proximity, unknown_alt) : unknown_alt); double mps_depth = (mpsusedepth ? wpt->depth : unknown_alt); lat = GPS_Math_Deg_To_Semi(wpt->latitude); diff --git a/ozi.c b/ozi.c index b33ccd89a..104de1354 100644 --- a/ozi.c +++ b/ozi.c @@ -421,7 +421,7 @@ ozi_parse_waypt(int field, char *str, waypoint * wpt_tmp, ozi_fsdata *fsdata) break; case 13: /* proximity distance - meters */ - wpt_tmp->proximity = atof(str); + WAYPT_SET(wpt_tmp, proximity, atof(str)); break; case 14: /* altitude in feet */ @@ -731,7 +731,7 @@ ozi_waypt_pr(const waypoint * wpt) "%d,%s,%.6f,%.6f,%.5f,%d,%d,%d,%d,%d,%s,%d,%d,", index, shortname, wpt->latitude, wpt->longitude, ozi_time, 0, 1, 3, fs->fgcolor, fs->bgcolor, description, 0, 0); - if (wpt->proximity > 0) + if (wpt->wpt_flags.proximity && (wpt->proximity > 0)) gbfprintf(file_out, "%.1f,", wpt->proximity); else gbfprintf(file_out,"0,"); diff --git a/stmsdf.c b/stmsdf.c index c52406170..8f0ded034 100644 --- a/stmsdf.c +++ b/stmsdf.c @@ -273,7 +273,7 @@ parse_point(char *line) case 0: wpt->speed = atof(str) * 3.6; break; case 3: - wpt->proximity = atof(str); + WAYPT_SET(wpt, proximity, atof(str)); xasprintf(&wpt->notes, "Alarm point: radius=%s", str); break; } diff --git a/unicsv.c b/unicsv.c index edef30b1a..227f68b03 100644 --- a/unicsv.c +++ b/unicsv.c @@ -21,52 +21,172 @@ #include "defs.h" #include "csv_util.h" #include "jeeps/gpsmath.h" +#include "strptime.h" +#include #define MYNAME "unicsv" -static gbfile *file_in; +typedef enum { + fld_shortname = 0, + fld_latitude, + fld_longitude, + fld_description, + fld_notes, + fld_url, + fld_altitude, + fld_utm_zone, + fld_utm_char, + fld_utm_northing, + fld_utm_easting, + fld_utm, + fld_bng, + fld_bng_zone, + fld_bng_northing, + fld_bng_easting, + fld_hdop, + fld_pdop, + fld_vdop, + fld_sat, + fld_fix, + fld_utc_date, + fld_utc_time, + fld_course, + fld_speed, + fld_temperature, + fld_temperature_f, + fld_heartrate, + fld_cadence, + fld_proximity, + fld_depth, + fld_terminator +} field_e; + +#define STR_LEFT 1 +#define STR_RIGHT 2 +#define STR_ANY 4 +#define STR_EQUAL 8 +#define STR_CASE 16 + +typedef struct { + char *name; + field_e type; + gbuint32 options; + +} field_t; -/* This structure must contain only ints. Firstval must be first. - * This is block initialized. +/* + * ! Use always underscores in field names ! + * we check a second time after replacing underscores with spaces */ -struct { - int firstval; - int latcol; - int loncol; - int namecol; - int desccol; - int notescol; - int altcol; - int urlcol; - int utmzcol; /* Zone */ - int utmncol; /* Northing */ - int utmecol; /* Easting */ - int utmccol; /* Zone character */ -} unicsv_fieldpos; +static field_t fields_def[] = { + { "name", fld_shortname, STR_ANY }, + { "descr", fld_description, STR_ANY }, + { "notes", fld_notes, STR_ANY }, + { "comment", fld_notes, STR_ANY }, + { "text", fld_notes, STR_ANY }, + { "url", fld_url, STR_ANY }, + { "lat", fld_latitude, STR_ANY }, + { "lon", fld_longitude, STR_ANY }, + { "alt", fld_altitude, STR_ANY }, + { "ele", fld_altitude, STR_ANY }, + { "utc_z", fld_utm_zone, STR_ANY }, + { "utm_c", fld_utm_char, STR_ANY }, + { "utm_n", fld_utm_northing, STR_ANY }, + { "utm_n", fld_utm_easting, STR_ANY }, + { "utm", fld_utm, STR_EQUAL }, + { "bng_z", fld_bng_zone, STR_ANY }, + { "bng_n", fld_bng_northing, STR_ANY }, + { "bng_n", fld_bng_easting, STR_ANY }, + { "bng", fld_bng, STR_EQUAL }, + { "hdop", fld_hdop, STR_ANY }, + { "pdop", fld_pdop, STR_ANY }, + { "vdop", fld_vdop, STR_ANY }, + { "sat", fld_sat, STR_ANY }, + { "fix", fld_fix, STR_ANY }, + { "utc_d", fld_utc_date, STR_ANY }, + { "utc_t", fld_utc_time, STR_ANY }, + { "head", fld_course, STR_ANY }, + { "course", fld_course, STR_ANY }, + { "speed", fld_speed, STR_ANY }, + { "tempf", fld_temperature_f, STR_EQUAL }, /* degrees fahrenheit */ + { "temp", fld_temperature, STR_ANY }, /* degrees celsius by default */ + { "heart", fld_heartrate, STR_ANY }, + { "cadence", fld_cadence, STR_ANY }, + { "prox", fld_proximity, STR_ANY }, + { "depth", fld_depth, STR_ANY }, + { NULL, fld_terminator, 0 } +}; +static field_e *unicsv_fields_tab; +static int unicsv_fields_tab_ct; static double unicsv_altscale; static char *unicsv_fieldsep; +static gbfile *file_in; +static gpsdata_type unicsv_data_type; +static route_head *unicsv_track; + +static arglist_t unicsv_args[] = { ARG_TERMINATOR }; -static -arglist_t unicsv_args[] = { - ARG_TERMINATOR -}; /* helpers */ // #define UNICSV_IS(f) (0 == strcmp(s, f)) #define UNICSV_CONTAINS(f) (0 != strstr(s, f)) +static char +unicsv_compare_fields(char *s, const field_t *f) +{ + char *name = (char *)f->name; + char *test = s; + char result; + + if (! (f->options & STR_CASE)) { + test = strupper(xstrdup(s)); + name = strupper(xstrdup(f->name)); + } + + if (f->options & STR_EQUAL) { + result = (strcmp(test, name) == 0); + } + else if (f->options & STR_ANY) { + result = (strstr(test, name) != NULL); + } + else { + int len = strlen(name); + + if (f->options & STR_LEFT) { + result = (strncmp(test, name, len) == 0); + } +/* + else if (f->options & STR_RIGHT) { + result = (strrncmp(test, name, len) == 0); + } +*/ + else { + result = 0; /* what should we do here ? */ + } + } + + if ((! result) && (strchr(test, ' ') != NULL)) { + char *tmp = gstrsub(test, " ", "_"); + result = unicsv_compare_fields(tmp, f); + xfree(tmp); + } + + if (name != f->name) { + xfree(name); + xfree(test); + } + + return result; +} + + static void unicsv_fondle_header(char *ibuf) { char *s; - unsigned int i; - int *ip = &unicsv_fieldpos.firstval; - - for (i = 0; i < sizeof(unicsv_fieldpos) / sizeof(int); i++, ip++) { - *ip = -1; - } + int i, column; /* Convert the entire header to lower case for convenience. * If we see a tab in that header, we decree it to be tabsep. @@ -84,45 +204,38 @@ unicsv_fondle_header(char *ibuf) } } - s = csv_lineparse(ibuf, unicsv_fieldsep, "", 0); - for (i=0; s; i++,s = csv_lineparse(NULL, unicsv_fieldsep, "", 0)) { - if (UNICSV_CONTAINS("lat")) { - unicsv_fieldpos.latcol = i; - } - else if (UNICSV_CONTAINS("lon")) { - unicsv_fieldpos.loncol = i; - } - else if (UNICSV_CONTAINS("desc")) { - unicsv_fieldpos.desccol = i; - } - else if (UNICSV_CONTAINS("name")) { - unicsv_fieldpos.namecol = i; + column = -1; + while ((s = csv_lineparse(ibuf, unicsv_fieldsep, "", 0))) { + + field_t *f = &fields_def[0]; + + ibuf = NULL; + column++; + unicsv_fields_tab_ct++; + s = lrtrim(s); + + if (column % 4 == 0) { + int sz = (column + 4) * sizeof(*unicsv_fields_tab); + if (column == 0) unicsv_fields_tab = xmalloc(sz); + else unicsv_fields_tab = xrealloc(unicsv_fields_tab, sz); + for (i = 0; i < 4; i++) unicsv_fields_tab[column + i] = fld_terminator; } - else if (UNICSV_CONTAINS("notes")) { - unicsv_fieldpos.notescol = i; + + while (f->name) { + if (unicsv_compare_fields(s, f)) { + unicsv_fields_tab[column] = f->type; + break; + } + f++; } - else if (UNICSV_CONTAINS("alt")) { - unicsv_fieldpos.altcol = i; + + /* handle some special items */ + if (f->type == fld_altitude) { if (UNICSV_CONTAINS("ft") || UNICSV_CONTAINS("feet")) { unicsv_altscale = FEET_TO_METERS(1); } } - else if (UNICSV_CONTAINS("url")) { - unicsv_fieldpos.urlcol = i; - } - else if (UNICSV_CONTAINS("utm z")) { - unicsv_fieldpos.utmzcol = i; - } - else if (UNICSV_CONTAINS("utm n")) { - unicsv_fieldpos.utmncol = i; - } - else if (UNICSV_CONTAINS("utm e")) { - unicsv_fieldpos.utmecol = i; - } - else if (UNICSV_CONTAINS("utm c")) { - unicsv_fieldpos.utmccol = i; - } -/* todo: speed, course, hdop, sat, date, time, maybe a few others */ +/* todo: date, time, maybe a few others */ } } @@ -131,6 +244,11 @@ unicsv_rd_init(const char *fname) { char *c; unicsv_altscale = 1.0; + + unicsv_fields_tab = NULL; + unicsv_fields_tab_ct = 0; + unicsv_data_type = wptdata; + unicsv_track = NULL; file_in = gbfopen(fname, "rb", MYNAME); @@ -144,65 +262,236 @@ static void unicsv_rd_deinit(void) { gbfclose(file_in); + if (unicsv_fields_tab) xfree(unicsv_fields_tab); } static void unicsv_parse_one_line(char *ibuf) { char *s; - waypoint *wpt; - int i; + waypoint *wpt = NULL; + int column; int utmz = -9999; double utme = 0; double utmn = 0; char utmc = 'N'; + char bng_zone[3] = ""; + double bng_easting = 0; + double bng_northing = 0; + struct tm tm; + char *ok; + int checked = 0; - s = csv_lineparse(ibuf, unicsv_fieldsep, "\"", 0); - if (s == NULL) return; - wpt = waypt_new(); + column = -1; + while ((s = csv_lineparse(ibuf, unicsv_fieldsep, "\"", 0))) { + + if (column > unicsv_fields_tab_ct) break; /* extra fields on line */ - for (i=0; s; i++, s = csv_lineparse(NULL, unicsv_fieldsep, "\"", 0)) { + ibuf = NULL; + column++; + checked++; s = lrtrim(s); - if (i == unicsv_fieldpos.latcol) { + + switch(unicsv_fields_tab[column]) { + + case fld_latitude: human_to_dec( s, &wpt->latitude, &wpt->longitude, 1 ); - } - else if (i == unicsv_fieldpos.loncol) { + break; + + case fld_longitude: human_to_dec( s, &wpt->latitude, &wpt->longitude, 2 ); - } - else if (i == unicsv_fieldpos.namecol) { - wpt->shortname = xstrdup(s); - } - else if (i == unicsv_fieldpos.desccol) { - wpt->description = xstrdup(s); - } - else if (i == unicsv_fieldpos.notescol) { - wpt->notes = xstrdup(s); - } - else if (i == unicsv_fieldpos.urlcol) { - wpt->url = xstrdup(s); - } - else if (i == unicsv_fieldpos.altcol) { + break; + + case fld_shortname: + if (*s) wpt->shortname = xstrdup(s); + break; + + case fld_description: + if (*s) wpt->description = xstrdup(s); + break; + + case fld_notes: + if (*s) wpt->notes = xstrdup(s); + break; + + case fld_url: + if (*s) wpt->url = xstrdup(s); + break; + + case fld_altitude: wpt->altitude = atof(s) * unicsv_altscale; - } - else if (i == unicsv_fieldpos.utmzcol) { + break; + + case fld_utm_zone: utmz = atoi(s); - } - else if (i == unicsv_fieldpos.utmecol) { + break; + + case fld_utm_easting: utme = atof(s); - } - else if (i == unicsv_fieldpos.utmncol) { + break; + + case fld_utm_northing: utmn = atof(s); - } - else if (i == unicsv_fieldpos.utmccol) { + break; + + case fld_utm_char: utmc = toupper(s[0]); + break; + + case fld_utm: + parse_coordinates(s, DATUM_WGS84, grid_utm, + &wpt->latitude, &wpt->longitude, MYNAME); + break; + + case fld_bng: + parse_coordinates(s, DATUM_OSGB36, grid_bng, + &wpt->latitude, &wpt->longitude, MYNAME); + break; + + case fld_bng_zone: + strncpy(bng_zone, s, sizeof(bng_zone)); + strupper(bng_zone); + break; + + case fld_bng_northing: + bng_northing = atof(s); + break; + + case fld_bng_easting: + bng_easting = atof(s); + break; + + case fld_hdop: + wpt->hdop = atof(s); + unicsv_data_type = trkdata; + break; + + case fld_pdop: + wpt->pdop = atof(s); + unicsv_data_type = trkdata; + break; + + case fld_vdop: + wpt->vdop = atof(s); + unicsv_data_type = trkdata; + break; + + case fld_sat: + wpt->sat = atoi(s); + unicsv_data_type = trkdata; + break; + + case fld_fix: + unicsv_data_type = trkdata; + if (case_ignore_strcmp(s, "none") == 0) + wpt->fix = fix_none; + else if (case_ignore_strcmp(s, "2d") == 0) + wpt->fix = fix_2d; + else if (case_ignore_strcmp(s, "3d") == 0) + wpt->fix = fix_3d; + else if (case_ignore_strcmp(s, "dgps") == 0) + wpt->fix = fix_dgps; + else if (case_ignore_strcmp(s, "pps") == 0) + wpt->fix = fix_pps; + else wpt->fix = fix_unknown; + break; + + case fld_utc_date: + memset(&tm, 0, sizeof(tm)); + if (strchr(s, '.')) + ok = strptime(s, "%d.%m.%Y", &tm); + else + ok = strptime(s, "%d/%m/%Y", &tm); + if (ok) { + tm.tm_isdst = -1; + wpt->creation_time += mkgmtime(&tm); + } + else + fatal(MYNAME ": Could not convert date string (%s).\n", s); + break; + + case fld_utc_time: + memset(&tm, 0, sizeof(tm)); + if (strptime( s, "%H:%M:%S", &tm)) { + wpt->creation_time += ( + (SECONDS_PER_HOUR * tm.tm_hour) + + (60L * tm.tm_min) + tm.tm_sec + ); + } + break; + + case fld_speed: + wpt->speed = atof(s); + unicsv_data_type = trkdata; + break; + + case fld_course: + wpt->course = atof(s); + unicsv_data_type = trkdata; + break; + + case fld_temperature: + WAYPT_SET(wpt, temperature, atof(s)); + break; + + case fld_temperature_f: + WAYPT_SET(wpt, temperature, FAHRENHEIT_TO_CELSIUS(atof(s))); + break; + + case fld_heartrate: + wpt->heartrate = atoi(s); + unicsv_data_type = trkdata; + break; + + case fld_cadence: + wpt->cadence = atoi(s); + unicsv_data_type = trkdata; + break; + + case fld_proximity: + WAYPT_SET(wpt, proximity, atof(s)); + break; + + case fld_depth: + wpt->depth = atof(s); + break; + + case fld_terminator: /* dummy */ + checked--; + break; } } - if (utmz != -9999) { - GPS_Math_UTM_EN_To_WGS84(&wpt->latitude, &wpt->longitude, - utme, utmn, utmz, utmc); + + if (checked == 0) { + waypt_free(wpt); + return; + } + + if (utmz != -9999) { + GPS_Math_UTM_EN_To_Known_Datum(&wpt->latitude, &wpt->longitude, + utme, utmn, utmz, utmc, DATUM_WGS84); + } + + if (bng_zone[0]) { + if (! GPS_Math_UKOSMap_To_WGS84_M( + bng_zone, bng_easting, bng_northing, + &wpt->latitude, &wpt->longitude)) + fatal(MYNAME ": Unable to convert BNG coordinates (%s %.f %.f)!\n", + bng_zone, bng_easting, bng_northing); + } + + switch(unicsv_data_type) { + case trkdata: + if (! unicsv_track) { + unicsv_track = route_head_alloc(); + track_add_head(unicsv_track); + } + track_add_wpt(unicsv_track, wpt); + break; + default: + waypt_add(wpt); } - waypt_add(wpt); } static void -- 2.30.2